package com.hnblc.blcwms.rest.logistics.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hnblc.blcwms.common.constant.StringPool;
import com.hnblc.blcwms.common.interaction.Response;
import com.hnblc.blcwms.common.utils.CollectionsUtils;
import com.hnblc.blcwms.common.utils.WmsTimeUtils;
import com.hnblc.blcwms.persistent.business.odata.vo.ExpressInfoBody;
import com.hnblc.blcwms.persistent.business.odata.vo.ExpressInfoHead;
import com.hnblc.blcwms.rest.config.properties.STOProperties;
import com.hnblc.blcwms.rest.logistics.enums.STOResultEnum;
import com.hnblc.blcwms.serviceapi.api.dto.logistics.WaybillInfo;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
public class STOService implements ILogisticServiceTypeB {

    @Autowired
    STOProperties stoProperties;

    @Autowired
    ObjectMapper objectMapper;

    RestTemplate restTemplate;
    public STOService(){
        restTemplate = new RestTemplate();
        MappingJackson2HttpMessageConverter stoMappingJackson2HttpMessageConverter =
                new MappingJackson2HttpMessageConverter();
        List<MediaType> mediaTypes = new ArrayList<>();
        mediaTypes.add(MediaType.TEXT_PLAIN);
        mediaTypes.add(MediaType.TEXT_HTML);
        stoMappingJackson2HttpMessageConverter.setSupportedMediaTypes(mediaTypes);
        restTemplate.getMessageConverters().add(stoMappingJackson2HttpMessageConverter);
    }
    @Override
    public Response<WaybillInfo> getWaybillInfo(ExpressInfoHead expressInfoHead) {

        WaybillInfo waybillInfo = new WaybillInfo();
        STOResponse<List<STOResponse.DeliveryAddressInfo>> waybillRes;
        MultiValueMap<String,Object> getParam = this.buildSTORequest("vip0007");
        try {

            //构造请求实体数据
            List<STOWaybillParam> relist= new ArrayList<>();
            relist.add(this.buildSTORequestParam(expressInfoHead));
            getParam.add("data", objectMapper.writeValueAsString(relist));
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString());
            HttpEntity<MultiValueMap<String,Object>> httpEntity = new HttpEntity<>(getParam, headers);


            //构造返回类型
            ParameterizedTypeReference<STOResponse<List<STOResponse.DeliveryAddressInfo>>>  typeof =
                    new ParameterizedTypeReference<STOResponse<List<STOResponse.DeliveryAddressInfo>>>(){};



            ResponseEntity<STOResponse<List<STOResponse.DeliveryAddressInfo>>> waybillResEntity = restTemplate.exchange(stoProperties.getUrl(), HttpMethod.POST,httpEntity, typeof);

            waybillRes = waybillResEntity.getBody();
            if(waybillRes.getSuccess()&& waybillRes.getData()!=null){

                waybillInfo.setWaybillNo(waybillRes.getData().get(0).getExpno());
                //用仓别+exp_no代替订单号，方便更新
                waybillInfo.setObjectId(waybillRes.getData().get(0).getOrderno());
                waybillInfo.setDeliveryAddress(waybillRes.getData().get(0).getBigchar());
                waybillInfo.setEndBranchName(waybillRes.getData().get(0).getPackageName());
            }else
                return new Response<>(STOResultEnum.ERROR_RES_UPLOAD_INFO,new Object[]{
                        waybillRes.getData()
                });

        }catch (Exception e){
            return new Response<>(STOResultEnum.ERROR_UNKNOWN,new Object[]{
                    e.getMessage()
            });
        }
        return new Response<>(STOResultEnum.SUCCESS,waybillInfo);
    }

    @Override
    public Response<List<WaybillInfo>> getWaybillInfos(List<ExpressInfoHead> expressInfoHeads) {
        List<List<ExpressInfoHead>> taskList= new ArrayList<>();
        //由于拼多多接口最大一次请求10个订单，所以拆分为多次请求
        if (expressInfoHeads.size()>stoProperties.getBatchSize())
            taskList = CollectionsUtils.listSpilt(expressInfoHeads,stoProperties.getBatchSize());
        else
            taskList.add(expressInfoHeads);

        List<WaybillInfo> waybillInfos = new ArrayList<>();

        STOResponse<List<STOResponse.DeliveryAddressInfo>> waybillRes;
        StringBuffer errorBuffer = new StringBuffer();
        //初始化请求体
        MultiValueMap<String,Object> getParam = this.buildSTORequest("vip0007");
        for (List<ExpressInfoHead> task : taskList) {
            try {
                //构造请求实体数据
                List<STOWaybillParam> relist= new ArrayList<>();
                task.forEach(item ->
                    relist.add(this.buildSTORequestParam(item))
                );
                getParam.add("data", objectMapper.writeValueAsString(relist));
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
                headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString());
                HttpEntity<MultiValueMap<String,Object>> httpEntity = new HttpEntity<>(getParam, headers);
                //构造返回类型
                ParameterizedTypeReference<STOResponse<List<STOResponse.DeliveryAddressInfo>>>  typeof =
                        new ParameterizedTypeReference<STOResponse<List<STOResponse.DeliveryAddressInfo>>>(){};
                ResponseEntity<STOResponse<List<STOResponse.DeliveryAddressInfo>>> waybillResEntity = restTemplate.exchange(stoProperties.getUrl(), HttpMethod.POST,httpEntity, typeof);

                waybillRes = waybillResEntity.getBody();
                if(waybillRes.getSuccess()&& waybillRes.getData()!=null){
                    if (waybillRes.getData() instanceof List){
                        waybillRes.getData().forEach(item ->{
                            WaybillInfo waybillInfo = new WaybillInfo();
                            waybillInfo.setWaybillNo(item.getExpno());
                            //用仓别+exp_no代替订单号，方便更新
                            waybillInfo.setObjectId(item.getOrderno());
                            waybillInfo.setDeliveryAddress(item.getBigchar());
                            waybillInfo.setEndBranchName(item.getPackageName());
                            waybillInfos.add(waybillInfo);
                        });
                    }
                }else
                    errorBuffer.append(waybillRes.getData().toString());

            }catch (Exception e){
                 e.printStackTrace();
                 errorBuffer.append(e.getMessage());
            }
        }

        if (waybillInfos.size()==0){
            return new Response<>(STOResultEnum.ERROR_RES_UPLOAD_INFO,new Object[]{
                    errorBuffer.toString()
            });
        }
        if (waybillInfos.size()<expressInfoHeads.size()){
            return new Response<>(STOResultEnum.NOT_ALL_SUC,waybillInfos,new Object[]{
                    errorBuffer.toString()
            });
        }

        return new Response<>(STOResultEnum.SUCCESS,waybillInfos);
    }



    private STOWaybillParam buildSTORequestParam(ExpressInfoHead expressInfoHead){
        STOWaybillParam stWaybillParam = new STOWaybillParam();
        stWaybillParam.setSenddate(WmsTimeUtils.getCurrentDatetime());//寄件日期yyyy-MM-dd HH:mm:SS
        stWaybillParam.setSendsite(stoProperties.getBranchName());
        stWaybillParam.setSendcus(stoProperties.getCustomName());//申通网点维护客户名称（0009接口中的cusname）
        stWaybillParam.setSendperson(expressInfoHead.getSenderName());
        stWaybillParam.setSendtel(expressInfoHead.getSenderMobile());
        stWaybillParam.setReceivecus(expressInfoHead.getReceiveName());
        stWaybillParam.setReceiveperson(expressInfoHead.getReceiveName());
        stWaybillParam.setReceivetel(expressInfoHead.getReceiveMobile());
        stWaybillParam.setInputdate(WmsTimeUtils.getCurrentDatetime());//录入日期yyyy-MM-dd HH:mm:SS  当前系统时间
        stWaybillParam.setInputperson(stoProperties.getCustomName());
        stWaybillParam.setInputsite(stoProperties.getBranchName()); //录入网点
        stWaybillParam.setLasteditdate(WmsTimeUtils.getCurrentDatetime());
        stWaybillParam.setLasteditperson(stoProperties.getCustomName());//最后编辑人
        stWaybillParam.setLasteditsite(stoProperties.getBranchName());
        stWaybillParam.setRemark(expressInfoHead.getRemark()); //备注
        stWaybillParam.setReceiveprovince(expressInfoHead.getReceiveProvince());
        stWaybillParam.setReceivecity(expressInfoHead.getReceiveCity());
        stWaybillParam.setReceivearea(expressInfoHead.getReceiveZone());
        stWaybillParam.setReceiveaddress(expressInfoHead.getReceiveAddress());
        stWaybillParam.setSendprovince(expressInfoHead.getSenderProvince());
        stWaybillParam.setSendcity(expressInfoHead.getSenderCity());
        stWaybillParam.setSendarea(expressInfoHead.getSenderZone());
        stWaybillParam.setSendaddress(expressInfoHead.getSenderAddress());
        stWaybillParam.setBillno(expressInfoHead.getWaybillNo());
        //此处用于区分返回的唯一ID，方便处理
        stWaybillParam.setOrderno(expressInfoHead.getEnterpriseNo()
                .concat(StringPool.COMMON_SEPARATOR_SPLIT_COLON)
                .concat(expressInfoHead.getWarehouseNo())
                .concat(StringPool.COMMON_SEPARATOR_SPLIT_COLON)
                .concat(expressInfoHead.getExpNo()));
        Double sumWeight = 0.0;
        for (ExpressInfoBody body:expressInfoHead.getGoodsList()){
            sumWeight += body.getUnitWeight()*body.getPlanQty();
            stWaybillParam.setProductcode(body.getBarcode());
            stWaybillParam.setGoodsname(body.getGoodName());//内件品名
        }
        stWaybillParam.setWeight(sumWeight.toString());
        return stWaybillParam;
    }



    /**
     * 获取申通热敏单号号段
     * @param count 获取单号数量
     * @return Response<List<String>>热敏单号列表集合
     */
    public Response<List<String>> getWaybillNos(Integer count){
        MultiValueMap<String,Object> getParam = this.buildSTORequest("vip0009");
        getParam.add("len",count.toString());

        STOResponse<String> waybillRes;
        try {

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString());
            HttpEntity<MultiValueMap<String,Object>> httpEntity = new HttpEntity<>(getParam, headers);

            ResponseEntity<STOResponse> resEntity= restTemplate.postForEntity(stoProperties.getUrl(),httpEntity, STOResponse.class);
            waybillRes = (STOResponse<String>)resEntity.getBody();
        }catch (Exception e){
            e.printStackTrace();
            return new Response<>(STOResultEnum.ERROR_RES_GET_NO,new Object[]{
                    e.getMessage()
            });
        }
        if (waybillRes==null){
            return new Response<>(STOResultEnum.EMPTY_NO_DATA);
        }
        if (waybillRes.getSuccess()) {
            List<String> logNoList = waybillRes.getData() == null ? null : Arrays.asList(waybillRes.getData().split(StringPool.COMMON_SEPARATOR_SPLIT_COMMA));
            if (logNoList == null || logNoList.size() < 1)
                return new Response<>(STOResultEnum.EMPTY_NO_DATA);
            else
                return new Response<>(STOResultEnum.SUCCESS, logNoList);
        }else {
            return new Response<>(STOResultEnum.ERROR_RES_GET_NO,new Object[]{waybillRes.getData()});
        }
    }




    private MultiValueMap<String,Object> buildSTORequest(String serviceCode){

        MultiValueMap<String,Object> getParam = new LinkedMultiValueMap<>();
        getParam.add("code",serviceCode);
        getParam.add("cusname",stoProperties.getCustomName());
        getParam.add("cuspwd",stoProperties.getCustomPassword());
        getParam.add("cusite",stoProperties.getBranchName());
        getParam.add("data_digest",stoProperties.getSignature());
        return getParam;
    }
    @Data
    private static class STOResponse<T>{
        private Boolean success;
        private String message;
        private T data;

        @Data
        private static class DeliveryAddressInfo{
            private String orderno;
            private String bigchar;
            private String expno;
            private String packageName;
        }

    }


    @Data
    private class STOWaybillParam {
        private String billno;
        private String senddate;
        private String sendsite;
        private String sendcus;
        private String sendperson;
        private String sendtel;
        private String receivecus;
        private String receiveperson;
        private String receivetel;
        private String goodsname;
        private String inputdate;
        private String inputperson;
        private String inputsite;
        private String lasteditdate;
        private String lasteditperson;
        private String lasteditsite;
        private String remark;
        private String receiveprovince;
        private String receivecity;
        private String receivearea;
        private String receiveaddress;
        private String sendprovince;
        private String sendcity;
        private String sendarea;
        private String sendaddress;
        private String weight;
        private String productcode;
        private String orderno;
    }
}
